package falcon.script;

import java.lang.reflect.Field;

public final class FalconLangToken {

	public static final int STRING = 0;
	public static final int ARG = 1;
	public static final int IDENT = 2;
	public static final int SYMBOL = 3;
	public static final int KEYWORD = 4;
	public static final int OPERATOR = 5;
	
	public static final class Symbol {
		public static final String COMMA = ",";
		public static final String EQUAL = "=";
		public static final String EXCLAM = "!";
		public static final String DOT = ".";
		public static final String LPAR ="(";
		public static final String RPAR = ")";
		public static final String PLUS = "+";
		public static final String MINUS = "-";
		public static final String ASTERISK = "*";
		public static final String SLASH = "/";
		public static final String PERCENT = "%";
		public static final String TILDE = "~";
		public static final String LESS = "<";
		public static final String GREATER = ">";
	}
	
	public static final class Keyword {
		public static final String FUNC = "func";
		public static final String FLOW = "flow";
		public static final String SYS = "sys";
		public static final String IF = "if";
		public static final String THEN = "then";
		public static final String ELIF = "elif";
		public static final String ELSE = "else";
		public static final String END = "end";
		public static final String AND = "and";
		public static final String OR = "or";
		public static final String REUTRN = "return";
	}
	
	public static final class Operator {
		public static final String ASSIGN = Symbol.EQUAL;
		public static final String EQ = Symbol.EQUAL + Symbol.EQUAL;
		public static final String NE = Symbol.EXCLAM + Symbol.EQUAL;
		public static final String GT = Symbol.GREATER;
		public static final String GE = Symbol.GREATER + Symbol.EQUAL;
		public static final String LT = Symbol.LESS;
		public static final String LE = Symbol.LESS + Symbol.EQUAL;
		public static final String REF = Symbol.DOT;
		public static final String JOIN = Symbol.TILDE;
		public static final String ADD = Symbol.PLUS;
		public static final String SUB = Symbol.MINUS;
		public static final String MUL = Symbol.ASTERISK;
		public static final String DIV = Symbol.SLASH;
		public static final String MOD = Symbol.PERCENT;
	}
	
	public static boolean isSymbol(char ch) {
		for (int i = 0; i < s_symbolList.length; i ++) {
			if (ch == s_symbolList[i].charAt(0)) {
				return true;
			}
		}
		return false;
	}
	
	public static boolean isKeyword(FalconLangToken token) {
		for (int i = 0; i < s_keywordList.length; i ++) {
			if (s_keywordList[i].equals(token.value)) {
				return true;
			}
		}
		return false;
	}

	public static boolean isOperator(FalconLangToken token) {
		for (int i = 0; i < s_operatorList.length; i ++) {
			if (s_operatorList[i].equals(token.value)) {
				return true;
			}
		}
		return false;
	}
	
	public int type;
	public int row;
	public int column;
	public String value;

	public FalconLangToken(int type, int row, int column) {
		this.type = type;
		this.row = row;
		this.column = column;
		this.value = "";
	}
	
	public FalconLangToken(int type, String value) {
		this.type = type;
		this.row = 0;
		this.column = 0;
		this.value = value;
	}
	
	public void subLine(String line, int end) {
		if (end < line.length()) {
			this.value = line.substring(this.column, end);
		} else {
			this.value = line.substring(this.column);
		}
	}
	
	public boolean check(int type, String value) {
		return this.type == type && this.value.equals(value);
	}
	
	@Override
	public String toString() {
		return String.format("t=%d;r=%d;c=%d;v=%s", this.type, this.row, this.column, this.value);
	}
	
	private static <T> String[] fillList(Class<T> clazz) {
		Field[] fields = clazz.getDeclaredFields();
		String[] list = new String[fields.length];
		for (int i = 0; i < fields.length; i ++) {
			Field field = fields[i];
			try {
				list[i] = (String) field.get(clazz);
			} catch (IllegalArgumentException e) {
				return null;
			} catch (IllegalAccessException e) {
				return null;
			}
		}
		return list;
	}
	
	private static String[] s_symbolList;
	private static String[] s_keywordList;
	private static String[] s_operatorList;
	
	static {
		s_symbolList = fillList(Symbol.class);
		s_keywordList = fillList(Keyword.class);
		s_operatorList = fillList(Operator.class);
	}
}
